package com.cvtt.core;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Vector;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.packet.VCard;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.cvtt.common.AlarmUtil;
import com.cvtt.common.NetworkUtil;
import com.cvtt.common.UBase64;
import com.cvtt.common.Util;
import com.cvtt.xmpp.XMPPConfig;
import com.cvtt.xmpp.XMPPEngine;
import com.cvtt.xmpp.XMPPListener;
import com.cvtt.xmpp.cvttmessage.CVTTMessage;
import com.cvtt.xmpp.cvttmessage.CVTTMessageParser;
import com.cvtt.xmpp.cvttmessage.CVTTUserNode;
import com.voipAgent.TZMessage;
import com.voipAgent.XmppAgent;
import com.voipAgent.XmppAgent.XmppEventListener;


public class XMPPCore extends CoreEventHandler implements XMPPListener {


	private static final String LOG_TAG = "XMPPCore";

	private Context context;
	private XMPPEngine xmppEngine;
	public static boolean bExit;
	private String userName="";
	private String userPassword ="";

	private int RETRY_TIME = 180;
	
	public static final String XMPP_USER_NAME = "xmpp_user_name";
	public static final String XMPP_USER_PASSWORD = "xmpp_user_password";
	public final static String K_UNUMBER = "unumber";
	public final static String K_REMARK = "remark";
	

	private static XMPPCore xmppCore = null;
	private XmppEventListener xmppEventListener;

	public static synchronized XMPPCore getInstance(Context context, XmppEventListener eventListener) {
		if (xmppCore == null) {
			xmppCore = new XMPPCore(context,eventListener);
		}
		return xmppCore;
	}

	public static XMPPCore getXMPPCore() {
		return xmppCore;
	}

	private XMPPCore(Context context, XmppEventListener eventListener) {
		this.context = context;
		xmppEventListener = eventListener;
		xmppEngine = XMPPEngine.getInstance(context, this);
		
	}

	public boolean isOnline() {
		xmppEventListener.onXMPPIsOnline(xmppEngine.isOnline());
		return xmppEngine.isOnline();
	}


	public synchronized void loadContactsInfo(String ...strings) {
		
		if (strings == null || strings.length < 1)
			return;
		ArrayList<VCard> infos=new ArrayList<VCard>(strings.length);
		for (String uNumber : strings) {
			
			if (TextUtils.isEmpty(uNumber))
				continue;
			
			VCard vCardInfo = xmppEngine.getUserVCard(uNumber + "@" + XMPPConfig.XMPP_HOST);
			infos.add(vCardInfo);
		}
		xmppEventListener.onXMPPContactsInfoLoaded(infos);
	}

	public void sendMessage(TZMessage msg) {
		if (msg == null)
			return;
		String toJID = msg.getToNumber() + "@" + XMPPConfig.XMPP_HOST;
		String body = msg.getContent();
		if (msg.isVoice()) {
			CVTTMessage cvttMsg = new CVTTMessage();
			
			cvttMsg.setFromUid(msg.getFromNumber());
			cvttMsg.setType(CVTTMessage.CVTT_MSG_VOICE);

			String voiceContent = msg.getAttachment();
			cvttMsg.setAttachment(voiceContent);
			cvttMsg.setAudioTime(String.valueOf(msg.getAudioTime()));
			Vector<CVTTUserNode> toList = new Vector<CVTTUserNode>();
			CVTTUserNode toUser = new CVTTUserNode();
			toUser.setUID(msg.getToNumber());
			toList.add(toUser);
			cvttMsg.setToList(toList);
			body = cvttMsg.toXML();
		}

		Message xmppMsg = new Message(body);
		xmppMsg.setBody(body);
		xmppMsg.setPacketID(String.valueOf(System.currentTimeMillis()));
		xmppEngine.sendMessage(toJID, xmppMsg);
	}


	public void keepAlive() {
		if (!NetworkUtil.isAvailable(context)) {
			postCoreEvent(XmppAgent.U_AWAY, null);
		}
		else {
			postCoreEvent(XmppAgent.U_XMPP_KEEP_ALIVE, null);
		}
	}

	@Override
	public void handleCoreEvent(int event, Object data) {
		// TODO Auto-generated method stub
		switch (event) {
			case XmppAgent.U_START:
				xmppEngine.start();
				break;
			case XmppAgent.U_XMPP_LOGIN:
				HashMap<String, String> hashMap = (HashMap<String, String>) data;
//				ULogger.i(LOG_TAG, "sip login");
				if(TextUtils.isEmpty(userName)){
					userName = hashMap.get(XMPP_USER_NAME);
				}
				if(TextUtils.isEmpty(userPassword)){
					userPassword = hashMap.get(XMPP_USER_PASSWORD);
				}
				xmppEngine.setLoginInfo(userName, userPassword);
				if (NetworkUtil.isAvailable(context))
					xmppEngine.login();
				else
					runTimer(RETRY_TIME);
				break;
			case XmppAgent.U_STOP:
				runTimer(0);
				xmppEngine.stop();
				break;
			case XmppAgent.U_RESTART:
			case XmppAgent.U_RELOGIN:
				
				if (NetworkUtil.isAvailable(context))
					xmppEngine.reStart(userName, userPassword);
				else
					runTimer(RETRY_TIME);
				break;

			case XmppAgent.U_LOGOUT:
				xmppEngine.logout();
				break;
			case XmppAgent.U_AWAY:
				xmppEngine.stop();
				runTimer(RETRY_TIME);
				break;
			case XmppAgent.U_XMPP_KEEP_ALIVE:
				xmppEngine.keepAlive();
				//pwLock(false);
				break;

			case XmppAgent.U_SEND_MSG:
				if (NetworkUtil.isAvailable(context)) {
					TZMessage msg = (TZMessage) data;
					sendMessage(msg);
				}
				break;
			case XmppAgent.U_ADD_XMPP_CONTACT:
				if (NetworkUtil.isAvailable(context)) {
					HashMap<String, String> addInfo = (HashMap<String, String>) data;
					String strUid = addInfo.get(K_UNUMBER);
					String strRemark = addInfo.get(K_REMARK);
					xmppEngine.addContact(strUid, strRemark);
				}
				break;
			case XmppAgent.U_ACCEPT_XMPP_CONTACT:
				if (NetworkUtil.isAvailable(context)) {
					String uNumber = (String) data;

					/*UMsgLog newMsg = new UMsgLog();
					newMsg.setID(uNumber);
					newMsg.setStatus(UMsgLog.STATUS_TO);
					MsgLogManager.getInstance().updateMsgLogStatus(newMsg);*/

					xmppEngine.acceptContact(uNumber + "@" + XMPPConfig.XMPP_HOST);
				}
				break;
			case XmppAgent.U_DEL_XMPP_CONTACT:
				if (NetworkUtil.isAvailable(context)) {
					String uNumber = (String) data;
					xmppEngine.deleteContact(uNumber + "@" + XMPPConfig.XMPP_HOST);
				}
				break;
			case XmppAgent.U_LOAD_XMPP_CONTACT_INFO:
				String uid=(String) data;
				if(TextUtils.isEmpty(uid)){
					return;
				}
				if (NetworkUtil.isAvailable(context)) {
					
					xmppEngine.loadXMPPInfo(uid + "@" + XMPPConfig.XMPP_HOST);
				}
				break;

			case XmppAgent.U_LOAD_XMPP_CONTACTS_INFO:
				if (NetworkUtil.isAvailable(context))
//					loadContactsInfo();
					xmppCore.postCoreEvent(XmppAgent.U_UPDATE_CONTACTS_INFO, null);
				break;

			case XmppAgent.U_SET_INFO:
				if (NetworkUtil.isAvailable(context) && (data != null)) {
					VCard info = (VCard) data;
					xmppEngine.setVcard(info);
				}
				break;
			case XmppAgent.U_XMPP_EXIT:
				onExit();
				break;
			default:
				break;
		}
	}

	@Override
	public boolean postSyncCoreEvent(int event, Object data) {
		boolean result = true;
		
		return result;
	}

	@Override
	public void onLoginEvent(int code) {
		// TODO Auto-generated method stub
		if(code == XMPPEngine.LOGIN_OK) {
			xmppEventListener.onXMPPLoginSuccess();
		}
		else {
			xmppEventListener.onXMPPLoginError();
		}
//		XmppAgent.updateStatus();
		xmppEventListener.onXMPPUpdateStatus();
		
	}

	@Override
	public void onStatusEvent(int status) {
		// TODO Auto-generated method stub
		xmppEventListener.onXMPPUpdateStatus();
		if (status == XMPPEngine.STATUS_KICK) {
			xmppEventListener.onXMPPKick();
		}
	}

	@Override
	public void onMessageEvent(String msgID, int code) {
		// TODO Auto-generated method stub
		if (code == XMPPEngine.MSG_OK)
			xmppEventListener.onXMPPSendMessageSuccess(msgID);
		else
			xmppEventListener.onXMPPSendMessageError(msgID);
	}

	@Override
	public void onInfoLoaded(VCard info) {
		// TODO Auto-generated method stub
		xmppEventListener.onXMPPInfoLoad(info);
		// TODO:其它信息的处理
		// PreferencesUtil.setUserExtras(extraInfo);
	}

	@Override
	public void onContactsLoaded(Collection<RosterEntry> xmppRosters) {
		// TODO Auto-generated method stub
		if (xmppRosters == null)
			return;
		xmppEventListener.onXMPPContactsLoaded(xmppRosters);

	}

	@Override
	public void onAddContact(String jid, String remark) {
		// TODO Auto-generated method stub
		if (TextUtils.isEmpty(jid))
			return;
		String uNumber = Util.getUNumber(jid);
		if (TextUtils.isEmpty(uNumber))
			return;
		xmppEventListener.onXMPPAddContact(jid,remark);
	}

	@Override
	public void onDelContact(String jid) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onContactAdded(RosterEntry rosterEntry) {
		// TODO Auto-generated method stub
		String xmppURI = rosterEntry.getUser();
		if (TextUtils.isEmpty(xmppURI))
			return;
		String uNumber = Util.getUNumber(xmppURI);
		if (TextUtils.isEmpty(uNumber))
			return;
		xmppEventListener.onXMPPContactAdded(rosterEntry);
	}

	@Override
	public void onContactDeleted(String jid) {
		// TODO Auto-generated method stub
		if (TextUtils.isEmpty(jid))
			return;
		String uNumber = Util.getUNumber(jid);
		xmppEventListener.onXMPPContactDeleted(uNumber);
	}

	@Override
	public void onContactInfoLoaded(String jid, VCard info) {
		// TODO Auto-generated method stub
		String uNumber = Util.getUNumber(jid);
		xmppEventListener.onXMPPContactInfoLoaded(info);
	}

	@Override
	public void onRecvMessage(Message msg) {
		// TODO Auto-generated method stub
		if (msg == null)
			return;

		TZMessage newMsg = new TZMessage();

		CVTTMessageParser messageconentXml;
		File audioFile = null;
		String fromNumber = Util.getUNumber(msg.getFrom());
		String toNumber = Util.getUNumber(msg.getTo());
		String content = msg.getBody();
		newMsg.setFromNumber(fromNumber);
		newMsg.setToNumber(toNumber);

		int type = TZMessage.MSG_TEXT_RECV;
		String audioTime = "";

		String msgType = "";

		if (content.startsWith("<cvttmessage") || content.startsWith("<?xml")) {
			try {
				messageconentXml = new CVTTMessageParser(content);
			}
			catch (Exception e) {
				messageconentXml = null;
			}
			if (messageconentXml != null) {
				msgType = messageconentXml.getCVTTMessage().getType();
				if (msgType.equals(CVTTMessage.CVTT_MSG_VOICE)) {
					String attachmentAudio = messageconentXml.getCVTTMessage().getAttachment();
					audioTime = messageconentXml.getCVTTMessage().getAudioTime();
					// audioTime = audioTime + UMsgLog.VOICE_SUFFIX;
					audioFile = Util.writeAudioToFile(UBase64.decode(attachmentAudio), fromNumber + "_" + Util.getTimeSuffix(System.currentTimeMillis()));
					newMsg.setAttachment(attachmentAudio);
					newMsg.setAudioTime(Integer.valueOf(audioTime));
					newMsg.setContent(audioFile.getPath());
					type = TZMessage.MSG_VOICE_RECV;

				}
				else {
					return;
				}
			}

		}
		else {
			newMsg.setContent(content);
		}

		long curTime = System.currentTimeMillis();
		newMsg.setFromNumber(fromNumber);
		newMsg.setType(type);
		xmppEventListener.onXMPPRecvMessage(newMsg);
	}

	public void startTimer() {
		xmppEngine.resetAliveData();
		runTimer(xmppEngine.getPingPeriod());
	}

	public void stopTimer() {
		xmppEngine.resetAliveData();
		runTimer(0);
	}

	public synchronized void runTimer(int time) {
		AlarmUtil.alarm(null, time, XMPPTimerReceiver.class);
	}

	@Override
	public void onKeepAlive(int afterTime) {
		// TODO Auto-generated method stub
		runTimer(afterTime);
	}

	@Override
	public boolean isExited() {
		// TODO Auto-generated method stub
		return bExit;
	}

	@Override
	public void onExit() {
		super.onExit();
		runTimer(0);
		xmppEngine.stop();
		bExit = true;
	}
}
